package v1alpha1

import (
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// LogLevel -
type LogLevel string

const (
	// LogLevelDebug -
	LogLevelDebug LogLevel = "debug"
	// LogLevelInfo -
	LogLevelInfo LogLevel = "info"
	// LogLevelWarning -
	LogLevelWarning LogLevel = "warning"
	// LogLevelError -
	LogLevelError LogLevel = "error"
)

//ParseLogLevel parse log level
func ParseLogLevel(l string) LogLevel {
	switch l {
	case "debug":
		return LogLevelDebug
	case "info":
		return LogLevelInfo
	case "warning":
		return LogLevelWarning
	case "error":
		return LogLevelError
	default:
		return LogLevelInfo
	}
}

// RbdComponentSpec defines the desired state of RbdComponent
type RbdComponentSpec struct {
	// Number of desired pods. This is a pointer to distinguish between explicit
	// zero and not specified. Defaults to 1.
	// +optional
	Replicas *int32 `json:"replicas,omitempty"`
	// type of rainbond component
	Type string `json:"type,omitempty"`
	// version of rainbond component
	Version  string   `json:"version,omitempty"`
	LogLevel LogLevel `json:"logLevel,omitempty"`
	// Docker image name.
	Image string `json:"image,omitempty"`
	// Image pull policy.
	// One of Always, Never, IfNotPresent.
	// Defaults to Always if :latest tag is specified, or IfNotPresent otherwise.
	// Cannot be updated.
	ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
	// component config map
	Configs     map[string]string `json:"configs,omitempty"`
	PackagePath string            `json:"packagePath,omitempty"`
	//  Whether this component needs to be created first
	PriorityComponent bool `json:"priorityComponent"`
}

// ControllerType -
type ControllerType string

const (
	// ControllerTypeDeployment -
	ControllerTypeDeployment ControllerType = "deployment"
	// ControllerTypeDaemonSet -
	ControllerTypeDaemonSet ControllerType = "daemonset"
	// ControllerTypeStatefulSet -
	ControllerTypeStatefulSet ControllerType = "statefuleset"
	// ControllerTypeUnknown -
	ControllerTypeUnknown ControllerType = "unknown"
)

func (c ControllerType) String() string {
	return string(c)
}

// RbdComponentConditionType is a valid value for RbdComponentCondition.Type
type RbdComponentConditionType string

// These are valid conditions of pod.
const (
	// ClusterConfigCompeleted indicates whether the configuration of the rainbondcluster cluster is complete.
	ClusterConfigCompeleted RbdComponentConditionType = "ClusterConfigCompeleted"
	// ClusterConfigCompeleted indicates whether the rainbondpackage is ready.
	RainbondPackageReady RbdComponentConditionType = "RainbondPackageReady"
	// RbdComponentReady means all pods related to the rbdcomponent are ready.
	RbdComponentReady RbdComponentConditionType = "Ready"
)

// RbdComponentCondition contains details for the current condition of this rbdcomponent.
type RbdComponentCondition struct {
	// Type is the type of the condition.
	Type RbdComponentConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=PodConditionType"`
	// Status is the status of the condition.
	// Can be True, False, Unknown.
	// More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions
	Status corev1.ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=ConditionStatus"`
	// Last time the condition transitioned from one status to another.
	// +optional
	LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,4,opt,name=lastTransitionTime"`
	// Unique, one-word, CamelCase reason for the condition's last transition.
	// +optional
	Reason string `json:"reason,omitempty" protobuf:"bytes,5,opt,name=reason"`
	// Human-readable message indicating details about last transition.
	// +optional
	Message string `json:"message,omitempty" protobuf:"bytes,6,opt,name=message"`
}

// RbdComponentStatus defines the observed state of RbdComponent
type RbdComponentStatus struct {
	// Total number of non-terminated pods targeted by this deployment (their labels match the selector).
	// +optional
	Replicas int32 `json:"replicas,omitempty" protobuf:"varint,2,opt,name=replicas"`

	// Total number of ready pods targeted by this deployment.
	// +optional
	ReadyReplicas int32 `json:"readyReplicas,omitempty" protobuf:"varint,7,opt,name=readyReplicas"`

	// Current state of rainbond component.
	Conditions []RbdComponentCondition `json:"conditions,omitempty"`

	// A list of pods
	Pods []corev1.LocalObjectReference `json:"pods,omitempty"`
}

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// RbdComponent is the Schema for the rbdcomponents API
// +kubebuilder:subresource:status
// +kubebuilder:resource:path=rbdcomponents,scope=Namespaced
type RbdComponent struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   RbdComponentSpec    `json:"spec,omitempty"`
	Status *RbdComponentStatus `json:"status,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// RbdComponentList contains a list of RbdComponent
type RbdComponentList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []RbdComponent `json:"items"`
}

func init() {
	SchemeBuilder.Register(&RbdComponent{}, &RbdComponentList{})
}

// ImagePullPolicy returns the ImagePullPolicy, or  return PullAlways if it is empty.
func (in *RbdComponent) ImagePullPolicy() corev1.PullPolicy {
	if in.Spec.ImagePullPolicy == "" {
		return corev1.PullAlways
	}
	return in.Spec.ImagePullPolicy
}

// LogLevel returns the LogLevel, or  return LogLevelInfo if it is empty.
func (in *RbdComponent) LogLevel() LogLevel {
	if in.Spec.LogLevel == "" {
		return LogLevelInfo
	}
	return in.Spec.LogLevel
}
